import java.util.*;

public class AVLManager 
{
	ArrayList<AVLSymbolTable> symTab;	
	String currentType;
	HashMap<String, AVLFunction> fTable;
	private static boolean debug = false;

	public AVLManager()
	{		
		symTab = new ArrayList<AVLSymbolTable>();
		currentType = "";
		fTable = new HashMap<String, AVLFunction>();
	}

	public void push(String scope)
	{
		AVLSymbolTable newSymTab = new AVLSymbolTable(scope);
		symTab.add(newSymTab);
	}

	public void push()
	{
		AVLSymbolTable newSymTab = new AVLSymbolTable();
		symTab.add(newSymTab);
	}

	public void pop()
	{
		symTab.remove(symTab.size() - 1);
	}

	public boolean addVariable(String name, Integer type)
	{
		if(debug)
			System.out.println("Entering "+name+" of type "+type);
		AVLSymbolTable current = symTab.get(symTab.size()-1);
		if(current.containsKey(name))
			return false;
		else {
			current.put(name, type);
			return true;
		}
	}

	public Integer checkVariable(String name)
	{
		int i;
		AVLSymbolTable current;

		if(debug) {
			System.out.println("Looking up "+name);
		}

		for(i = symTab.size() - 1; i >= 0; i--) {
			current = symTab.get(i);
			if(current.containsKey(name)) {
				if(debug)
					System.out.println("Variable "+name+" exists!!");
				return (Integer) current.get(name);
			}
		}
		if(debug) {
			System.out.println("Variable "+name + " not declared.");
		}
		return AVL.INV;
	}

	public boolean addFunction(String name, Integer retType, Object sign)
	{
		AVLFunction currentFunction = new AVLFunction();
		currentFunction.setFunctionName(name);
		currentFunction.setFunctionType(retType);
		currentFunction.setParamTypes((ArrayList<Integer>)sign);
		if(debug) {
		  System.out.println("Adding function with signature: "+ name + " " + retType + " " + (ArrayList<Integer>)sign);
		}
		if(fTable.containsKey(name)) {
			return false;
		}
		else
			fTable.put(name, currentFunction);
		return true;
	}

	public Integer checkFunction(String fName, ArrayList<Integer> callList) {

		AVLFunction fun;
		ArrayList<Integer> pTypes;
		if(debug) {
			System.out.println("Looking up function with signature: "+fName + " " + callList);
		}
		if(fTable.containsKey(fName)) {
			fun = fTable.get(fName);
			pTypes = fun.getParamTypes();
			if(debug) {
				System.out.println("Found function with signature: "+fName + " " + pTypes);
			}
			if(callList.equals(pTypes))
				return fun.getFunctionType();			
		}
		return AVL.INV;
	}

	public Integer getFunctionReturnType(String fName)
	{
		AVLFunction fun = fTable.get(fName);

		if(fTable.containsKey(fName)) {
				return fun.getFunctionType();
		}
		return AVL.INV;
	}

}
